package com.stox.client.ui.javafx.watchlist.application;

import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;

import org.springframework.context.ApplicationEvent;
import org.springframework.context.event.SmartApplicationListener;
import org.springframework.stereotype.Component;

import com.stox.client.api.watchlist.event.AbstractWatchlistEvent;
import com.stox.client.api.watchlist.event.WatchlistAddedEvent;
import com.stox.client.api.watchlist.event.WatchlistDeletedEvent;
import com.stox.client.api.watchlist.event.WatchlistEditedEvent;
import com.stox.client.core.model.intf.HasNavigable;
import com.stox.client.ui.javafx.watchlist.widget.AddToWatchlistMenu;
import com.stox.client.ui.javafx.widget.ContextMenuConfigurer;
import com.stox.shared.model.intf.HasScrip;

@Component
public class WatchlistContextMenuConfigurer implements ContextMenuConfigurer, SmartApplicationListener{
	
	private List<AddToWatchlistMenu> menus = new ArrayList<>();
	
	@Override
	public void clear(ContextMenu contextMenu) {
		ListIterator<MenuItem> iterator = contextMenu.getItems().listIterator();
		while(iterator.hasNext()){
			MenuItem item = iterator.next();
			if(item instanceof AddToWatchlistMenu){
				iterator.remove();
			}
		}
	}
	
	@Override
	@SuppressWarnings("unchecked")
	public void configure(ContextMenu contextMenu) {
		if(contextMenu instanceof HasScrip){
			addMenuItems(contextMenu, (HasScrip)contextMenu, null);
		}else if(contextMenu instanceof HasNavigable){
			HasNavigable<?> hasNavigable = (HasNavigable<?>)contextMenu;
			if(HasScrip.class.isAssignableFrom(hasNavigable.getNavigable().getNavigableEntityClass())){
				addMenuItems(contextMenu, null, (HasNavigable<HasScrip>)contextMenu);
			}
		}
	}
	
	private void addMenuItems(ContextMenu contextMenu, HasScrip hasScrip, HasNavigable<HasScrip> hasNavigable){
		AddToWatchlistMenu menu = new AddToWatchlistMenu(hasScrip, hasNavigable);
		menus.add(menu);
		contextMenu.getItems().add(menu);
	}
	
	@Override
	public int getOrder() {
		return 0;
	}
	
	@Override
	public void onApplicationEvent(ApplicationEvent event) {
		if(WatchlistAddedEvent.class.isAssignableFrom(event.getClass())){
			for(AddToWatchlistMenu menu : menus){
				WatchlistAddedEvent watchlistAddedEvent = (WatchlistAddedEvent)event;
				menu.addWatchlist(watchlistAddedEvent.getWatchlist());
			}
		}else if(WatchlistEditedEvent.class.isAssignableFrom(event.getClass())){
			for(AddToWatchlistMenu menu : menus){
				WatchlistEditedEvent watchlistEditedEvent = (WatchlistEditedEvent)event;
				menu.updateWatchlist(watchlistEditedEvent.getWatchlist());
			}
		}else if(WatchlistDeletedEvent.class.isAssignableFrom(event.getClass())){
			for(AddToWatchlistMenu menu : menus){
				WatchlistDeletedEvent watchlistDeletedEvent = (WatchlistDeletedEvent)event;
				menu.deleteWatchlist(watchlistDeletedEvent.getId());
			}
		}
	}
	
	@Override
	public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
		return AbstractWatchlistEvent.class.isAssignableFrom(eventType) ||
				WatchlistDeletedEvent.class.isAssignableFrom(eventType);
	}
	
	@Override
	public boolean supportsSourceType(Class<?> sourceType) {
		return true;
	}

}
